(function(w) {
    var eyeAoiFactory = (function() {
        // eyeAoi object constructor
        var eyeAoi = function eyeAoi(config) {
            // private variables
            var _ = {
                element : null,// 绘制区域canvas,和其它绘制不一样，此处是传的id而非jquery对象
                datapoints : [],// 数据点集合
                color : "rgb(0,0,0)",// 颜色(暂未使用)
                diaphaneity : 0.3, // 透明度(暂未使用)
                worker : 1, // 多线程并发数(即待画图的被试个数)
                screenWidth : 1440,// 屏幕宽度
                screenHeight : 900,// 屏幕高度
                graphs : [], // 绘制的图形
                showType : 0
            // 显示类型
            };

            this.get = function(key) {
                return _[key];
            };
            this.set = function(key, value) {
                _[key] = value;
            };

            // configure the eyeAoi when an instance gets created
            this.configure(config);
            // and initialize it
            this.init();
        };

        // public functions
        eyeAoi.prototype = {
            configure : function(config) {
                var me = this;

                me.set("element", config.element || me.get("element"));
                me.set("datapoints", config.datapoints || me.get("datapoints"));
                me.set("color", config.color || me.get("color"));
                me.set("diaphaneity", config.diaphaneity || me.get("diaphaneity"));
                me.set("worker", config.worker || me.get("worker"));
                me.set("screenWidth", config.screenWidth || me.get("screenWidth"));
                me.set("screenHeight", config.screenHeight || me.get("screenHeight"));
                me.set("graphs", config.graphs || me.get("graphs"));
                me.set("showType", config.showType || me.get("showType"));
            },

            init : function() {
            },

            drawAoiByFiaxtion : function(isShowData) {
                var me = this;
                var canvasId = me.get("element");
                var context2D = $("#" + canvasId)[0].getContext("2d");
                var worker = me.get("worker");
                var objs = newPointModel(eval(me.get("datapoints")));
                var graphs = me.get("graphs");

                /** 0. 将所有AOI图层清空 */
                $("#" + canvasId).removeLayers();

                /** 1. 根据AOI图形类型，绘制图形 */
                for ( var i = 0; i < graphs.length; i++) {
                    if (graphs[i].type == AoiTypeEnum.POLYGON) { // 多边形
                        var layerObjs = {
                            type : 'line',
                            strokeStyle : graphs[i].strokeStyle,
                            strokeWidth : graphs[i].strokeWidth,
                            name : graphs[i].name,
                            fromCenter : false,
                            closed : true,
                            fillStyle : graphs[i].fillStyle,
                            x : graphs[i].x,
                            y : graphs[i].y
                        };

                        for ( var p = 0; p < graphs[i].poLength; p++) { // 遍历所有顶点
                            layerObjs['x' + (p + 1)] = graphs[i].points[p].x;
                            layerObjs['y' + (p + 1)] = graphs[i].points[p].y;
                        }

                        $("#" + canvasId).addLayer(layerObjs);

                    } else { // 矩形和圆形
                        $("#" + canvasId).addLayer({
                            type : graphs[i].type,
                            strokeStyle : graphs[i].strokeStyle,
                            strokeWidth : graphs[i].strokeWidth,
                            name : graphs[i].name,
                            fromCenter : false,
                            fillStyle : graphs[i].fillStyle,
                            x : graphs[i].x,
                            y : graphs[i].y,
                            width : graphs[i].width,
                            height : graphs[i].height
                        });
                    }
                }
                $("#" + canvasId).drawLayers();
                $("#" + canvasId).saveCanvas();

                /** 3. 遍历每个图形，计算其统计数据 */
                if (!isShowData) {
                    return;
                }
                var muliDataList = new Array(); // 每个AOI图形的统计数据集合
                for ( var p = 0; p < graphs.length; p++) {
                    var widthRate = graphs[p].canvasWidth / $("#" + canvasId).width(); // 画布宽的缩放比
                    var heightRate = graphs[p].canvasHeight / $("#" + canvasId).height(); // 画布高的缩放比
                    var mPoints = new Array(); // 多边形的顶点集合
                    if (graphs[p].type == AoiTypeEnum.POLYGON) {
                        for ( var k = 0; k < graphs[p].poLength; k++) {
                            mPoints.push({
                                x : graphs[p].points[k].x + graphs[p].x,
                                y : graphs[p].points[k].y + graphs[p].y
                            }); // 多边形所有图形，在拖动时只会变化x和y坐标，因此绘制、计算时需要与x和y坐标相加
                        }
                    }

                    var data = { // 初始化统计值
                        duration : 0, // 持续时长
                        fixCount : 0, // 注视点个数
                        firstStart : null, // 进入时间
                        hitCount : 0, // 结果命中数
                        hitCountRatio : 0, // 结果命中率 =
                        // (结果命中数/总的结果数即worker)
                        durationAvg : 0, // 持续时长(平均) = 持续时长 / 结果命中数
                        leftPupilSize : 0, // 左眼平均瞳孔
                        rightPupilSize : 0
                    // 右眼平均瞳孔
                    };

                    var isContain = false; // 注视点是否在AOI图形内
                    for ( var i = 0; i < worker; i++) { // 遍历结果数据集,计算所属的AOI,进而计算统计值
                        var hitCountIsCalc = false; // 该结果的命中数是否已计算
                        for ( var j = 0; j < objs[i].length; j++) {
                            if (graphs[p].type == AoiTypeEnum.RECTANGLE) {
                                isContain = isRectangleContainsPoint(graphs[p].x, graphs[p].y, graphs[p].width, graphs[p].height, {
                                    x : objs[i][j].x * widthRate,
                                    y : objs[i][j].y * heightRate
                                });
                            } else if (graphs[p].type == AoiTypeEnum.ELLIPSE) {
                                // graphs中的x和y是左上角的坐标，因此需要换算到圆形中心坐标
                                isContain = isEllipseContainsPoint(graphs[p].x + graphs[p].width / 2, graphs[p].y + graphs[p].height / 2, graphs[p].width, graphs[p].height, {
                                    x : objs[i][j].x * widthRate,
                                    y : objs[i][j].y * heightRate
                                });
                            } else if (graphs[p].type == AoiTypeEnum.POLYGON) {
                                isContain = isPolygonContainsPoint(mPoints, {
                                    x : objs[i][j].x * widthRate,
                                    y : objs[i][j].y * heightRate
                                });
                            }

                            if (isContain) {
                                if (!hitCountIsCalc) { // 只有注视点已在AOI中时，才用计算命中数
                                    data.hitCount++;
                                    hitCountIsCalc = true; // 每个结果只用计算一次
                                }

                                if (data.firstStart == null) { // 进入时长:取最小的进入时间
                                    data.firstStart = objs[i][j].fixStart;
                                } else {
                                    if (objs[i][j].fixStart < data.firstStart) {
                                        data.firstStart = objs[i][j].fixStart;
                                    }
                                }
                                data.fixCount++; // 注视点个数：自增
                                data.leftPupilSize += objs[i][j].LPS; // 左眼平均瞳孔：累加
                                data.rightPupilSize += objs[i][j].RPS; // 右眼平均瞳孔：累加
                                data.duration += objs[i][j].fixDur; // 持续时长：累加
                            }
                            isContain = false;
                        }
                    }

                    /** 汇总计算其它统计值 */
                    data.durationAvg = Math.round(data.duration / data.hitCount); // 平均持续时长
                    data.hitCountRatio = Math.round(data.hitCount / worker * 100); // 结果命中率
                    // 左眼平均瞳孔: 需按注视点个数平均
                    data.leftPupilSize = Math.round(data.leftPupilSize * 100 / data.fixCount) / 100;
                    // 右眼平均瞳孔: 需按注视点个数平均
                    data.rightPupilSize = Math.round(data.rightPupilSize * 100 / data.fixCount) / 100;

                    muliDataList.push({
                        name : graphs[p].name,
                        data : data
                    });
                }

                return muliDataList;

            },
            clearup : function() {
            }
        };

        return {
            create : function(config) {
                return new eyeAoi(config);
            }
        };
    })();

    w.eyeAoi = w.eyeAoiFactory = eyeAoiFactory;
})(window);
